package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.OcrUtil;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.dto.ArticleDto;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleFeign;
import com.heima.media.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AuditServiceImpl implements IAuditService {


    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    @Lazy // 解决循环依赖问题
    private IWmNewsService wmNewsService;

    @Autowired
    private MinIOService minIOService;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private IWmUserService wmUserService;

    @Autowired
    private IWmChannelService wmChannelService;

    @Override
    public void audit(Integer newsId) {
        WmNews wmNews = wmNewsService.getById(newsId);
        audit(wmNews);
    }

    @Override
    @Async // 标明要异步调用
    public void audit(WmNews wmNews) {

        boolean flag = true;

//        自管理敏感词的审核
        flag = checkSensitive(wmNews);
        if (!flag) return;

//        审核自媒体文章的文本内容
        flag = checkText(wmNews);
        if (!flag) return;

//        审核自媒体文章的图片内容
        flag = checkImages(wmNews);
        if (!flag) return;

//        审核通过  feign远程调用 保存apArticle
//        还需要判断是否到达发布时
//          如果当前时间>发布时间，就意味着已经达到发布时间
//        if(new Date().getTime() > wmNews.getPublishTime().getTime() ){
        if (System.currentTimeMillis() > wmNews.getPublishTime().getTime()) {
//            达到发布时间
//            feign远程调用 保存apArticle
            Long articleId = saveApArticle(wmNews);
            wmNews.setArticleId(articleId);
            wmNews.setStatus(9);
            wmNewsService.updateById(wmNews);
        } else {
//            只修改一下状态
            wmNews.setStatus(8);
            wmNewsService.updateById(wmNews);


            //            使用Redisson做延迟任务
//            RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque("news-dqueue");
            RBlockingDeque<Integer> blockingDeque = redissonClient.getBlockingDeque("publish-article-queue");
//        根据blockingDeque获取延迟队列
            RDelayedQueue<Integer> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
//        放数据

//            即将发布的时间-当前时间
            long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
            delayedQueue.offer(wmNews.getId(), time, TimeUnit.MILLISECONDS);
            log.info("延迟消息发送成功，预计在" + time + "毫秒后，会执行某一个方法" + new Date());

        }
    }

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IWmSensitiveService sensitiveService;

    private boolean checkSensitive(WmNews wmNews) {
        String text = wmNews.getTitle();
        //        从Content中提取文本
        List<ContentDto> contentDtos = JSON.parseArray(wmNews.getContent(), ContentDto.class);
        for (ContentDto contentDto : contentDtos) {
            if (contentDto.getType().equals("text")) {
                text += contentDto.getValue();
            }
        }

        //        构建一个DFA算法的Map
        List<WmSensitive> list = sensitiveService.list();
        List<String> sensitiveWords = new ArrayList<>();
        for (WmSensitive sensitive : list) {
            sensitiveWords.add(sensitive.getSensitives());
        }
        SensitiveWordUtil.initMap(sensitiveWords);
        Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(text);
        //        stringIntegerMap = {小额贷款=1, 随机随贷=1, 无抵押=2}
        if (stringIntegerMap.size() > 0) { //表示内容中有敏感词 不通过的
            Set<String> strings = stringIntegerMap.keySet();
            String reason = String.join(",", strings); //把key的set集合转成字符串
            wmNews.setStatus(2);
            wmNews.setReason("敏感词审核未通过，原因是包含以下敏感词：" + reason); //审核不通过或需要人工审核的原因
            wmNewsService.updateById(wmNews);
            return false;
        } else {
            return true;
        }
    }


    //    远程发布app文章
    @Override
    public Long saveApArticle(WmNews wmNews) {
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());

        ArticleDto articleDto = new ArticleDto();
        articleDto.setContent(wmNews.getContent());
        articleDto.setTitle(wmNews.getTitle());
        articleDto.setAuthorId(wmUser.getApAuthorId());
        articleDto.setAuthorName(wmUser.getName());
        articleDto.setChannelId(wmNews.getChannelId());

        WmChannel wmChannel = wmChannelService.getById(wmNews.getChannelId());

        articleDto.setChannelName(wmChannel.getName());
        articleDto.setLayout(wmNews.getType());
        articleDto.setFlag(0);

//        List<String> collect = JSON.parseArray(wmNews.getImages(), ImageDto.class).stream().map(dto -> {
//            return dto.getUrl();
//        }).collect(Collectors.toList());

        List<ImageDto> imageDtoList = JSON.parseArray(wmNews.getImages(), ImageDto.class);
//        List<String> urlList = new ArrayList<>();
//        for (ImageDto imageDto : imageDtoList) {
//            urlList.add(imageDto.getUrl());
//        }

        List<String> urlList = imageDtoList.stream().map(ImageDto::getUrl).collect(Collectors.toList());

        articleDto.setImages(String.join(",", urlList)); //用逗号分隔每个url

        articleDto.setLabels(wmNews.getLabels());
        articleDto.setPublishTime(wmNews.getPublishTime());
        ResponseResult<Long> responseResult = articleFeign.saveArticle(articleDto);
        return responseResult.getData();

    }

    private boolean checkImages(WmNews wmNews) {
//        图片有两种：内容图片+封面图片
        List<String> allUrlList = new ArrayList<>();

//        获取内容图片
        List<ContentDto> contentDtoList = JSON.parseArray(wmNews.getContent(), ContentDto.class);
        for (ContentDto contentDto : contentDtoList) {
            if (contentDto.getType().equals("image")) {
                allUrlList.add(contentDto.getValue());
            }
        }

        String images = wmNews.getImages();
//        [{"id":262,"url":"http://192.168.85.143:9000/heima/91198f22-0274-4156-8d1b-09835e7990bd.jpeg"},
//        {"id":263,"url":"http://192.168.85.143:9000/heima/3b0383e6-18c7-4891-9606-6703c2b8d3e5.jpeg"},
//        {"id":264,"url":"http://192.168.85.143:9000/heima/4e342011-dd0c-4a5b-8005-ad065ab43056.jpeg"}]
        List<ImageDto> imageDtoList = JSON.parseArray(images, ImageDto.class);
        for (ImageDto imageDto : imageDtoList) {
            if (!allUrlList.contains(imageDto.getUrl())) {
                allUrlList.add(imageDto.getUrl());
            }
        }
//        要从minio中下载图片
        try {
            List<byte[]> byteList = new ArrayList<>();
            for (String url : allUrlList) {
                InputStream inputStream = minIOService.download(url);
                byte[] bytes = IOUtils.toByteArray(inputStream);
                byteList.add(bytes);
            }

            String imageText = OcrUtil.ocrCheck(byteList);
            log.error("图片文字：{}"+imageText);
            if(StringUtils.isNotBlank(imageText)){
                //        构建一个DFA算法的Map
                List<WmSensitive> list = sensitiveService.list();
                List<String> sensitiveWords = new ArrayList<>();
                for (WmSensitive sensitive : list) {
                    sensitiveWords.add(sensitive.getSensitives());
                }
                SensitiveWordUtil.initMap(sensitiveWords);
                Map<String, Integer> map = SensitiveWordUtil.matchWords(imageText);
                log.error("匹配：{}"+map.size());
                if (map.size()>0) { // 代表有敏感词
//          map格式；  {小额贷款=1, 随机随贷=2, 无抵押=1}
//            map.keySet()
                    String reason = String.join(",", map.keySet());
                    wmNews.setStatus(2); //审核失败
                    wmNews.setReason("自管理敏感词文本审核失败的原因是："+reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
            }


            Map map = greenImageScan.imageScan(byteList);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass": {
                    return true;
                }
                case "review": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(3); //需要人工审核
                    wmNews.setReason("图片需要人工审核，图片审核不通过的原因是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
                case "block": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(2); //需要人工审核
                    wmNews.setReason("图片审核审核失败的原因是是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;

    }

    private boolean checkText(WmNews wmNews) {
//        文本审核
//        文本=标题+文章内容
        String text = wmNews.getTitle();

//        获取文章内容
        //        文章内容格式如下
//        "[
//        {
//            "type":"text",
//                "value":"随着智能手机的普及，人们更加习惯于通过手机来看新闻。由于生活节奏的加快，很多人只能利用碎片时间来获取信息，因此，对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯，通过大数据分析用户喜好精确推送咨询新闻"
//        },
//        {
//            "type":"image",
//                "value":"http://192.168.200.130/group1/M00/00/00/wKjIgl5swbGATaSAAAEPfZfx6Iw790.png",
//                "id" :176
//        }
//]"
        List<ContentDto> contentDtoList = JSON.parseArray(wmNews.getContent(), ContentDto.class);
        for (ContentDto contentDto : contentDtoList) {
            if (contentDto.getType().equals("text")) {
                text += contentDto.getValue();
            }
        }
        try {
            Map map = greenTextScan.greenTextScan(text);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass": {
                    return true;
                }
                case "review": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(3); //需要人工审核
                    wmNews.setReason("文本需要人工审核，文本审核不通过的原因是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
                case "block": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(2); //需要人工审核
                    wmNews.setReason("文本审核审核失败的原因是是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
                default:
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


}
